#ifndef _STACK_H_
#define _STACK_H_

/**
 *******************************************************************************
 * @brief    stack operation
 * @author                
 * @since 
 *
 *******************************************************************************/
template<typename TData> struct CStackNode
{
	CStackNode() : itsData(TData()), itsNextNode(NULL)
	{
	}

	TData itsData;
	CStackNode<TData>* itsNextNode;
};

template<typename TData> class CStack
{
public:
	CStack() : itsSize(0), itsTopElement(NULL)
	{
	}

	inline bool empty() const { return 0 == itsSize; }
	inline unsigned int size() const { return itsSize; }
	void push(const TData& value);
	void pop();
	TData& top();
	const TData& top() const;

private:
	unsigned int itsSize;
	CStackNode<TData>* itsTopElement;
};

template<typename TData>
void CStack<TData>::push(const TData& value)
{
	CStackNode<TData>* newNode = new CStackNode<TData>();
	newNode->itsData = value;
	newNode->itsNextNode = itsTopElement;
	itsTopElement = newNode;
	++itsSize;
}

template<typename TData>
void CStack<TData>::pop()
{
	if(empty())
	{
		return;
	}
	CStackNode<TData>* nextNode = itsTopElement->itsNextNode;
	delete itsTopElement;
	itsTopElement = nextNode;
	--itsSize;
}

/**
 * top - return top element in the stack
 * @value:	the data to be inserted
 */
template<typename TData>
TData& CStack<TData>::top()
{
	// here, no judge empty stack, user should judge by self
/*
	if(empty())
	{
		return;
	}
*/
	return itsTopElement->itsData;
}

template<typename TData>
const TData& CStack<TData>::top() const
{
	// here, no judge empty stack, user should judge by self
/*
	if(empty())
	{
		return;
	}
*/
	return itsTopElement->itsData;
}

#endif  // _CSTACK_H_